<!--
#-------------------------------------------------------------------------------
# Copyright 2011 Devesh Parekh
# 
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# 
#   http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#-------------------------------------------------------------------------------
-->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="com.opentok.api.OpenTokSDK" %>
<%@ page import="com.google.appengine.api.users.UserService" %>
<%@ page import="com.google.appengine.api.users.UserServiceFactory" %>
<%@ page import="com.google.common.base.CharMatcher" %>
<%@ page import="javax.jdo.PersistenceManager" %>
<%@ page import="com.appspot.tokroom.Constants" %>
<%@ page import="com.appspot.tokroom.data.PMF" %>
<%@ page import="com.appspot.tokroom.data.Room" %>

<%
    String room = request.getParameter("room");
    if (room == null) {
      response.sendRedirect("/");
      return;
    }
    room = CharMatcher.JAVA_LETTER_OR_DIGIT.or(CharMatcher.WHITESPACE).retainFrom(room);
    Room roomConfig = null;
    PersistenceManager pm = PMF.get().getPersistenceManager();
    try {
      roomConfig = pm.getObjectById(Room.class, room);
    } catch (javax.jdo.JDOObjectNotFoundException e) {
      response.sendRedirect("manage.jsp?room=" + room);
    } finally {
      pm.close();
    }
    UserService userService = UserServiceFactory.getUserService();
    if (!roomConfig.isAllowed(userService.getCurrentUser().getEmail())) {
      response.sendError(403, "You are not authorized to join this room.");
      return;
    }
%>

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title><%= room %></title>
<script src="//static.opentok.com/v0.91/js/TB.min.js"></script>
<script src="//ajax.microsoft.com/ajax/jquery/jquery-1.5.min.js"></script>
<script src="//ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js"></script>
<script src="/jquery.cookie.js"></script>
<script src="/iphone-style-checkboxes.js"></script>
<link rel="stylesheet" href="/style.css" type="text/css" media="screen"/>
<script id="subscribetemplate" type="text/x-jquery-tmpl">
<div id="toggle\${streamId}" style="display:inline-block">
  <input id="check\${streamId}" type="checkbox" onchange="javascript:redrawStreams()" {{if checked}}checked{{/if}}/>
</div>
</script>
<script type="text/javascript" charset="utf-8">
  var apiKey = 274841;
  var sessionId = "<%= roomConfig.getSessionId() %>"
  var token = "<%=
    new OpenTokSDK(Constants.API_KEY, Constants.API_SECRET)
        .generate_token(roomConfig.getSessionId(), null, 7*86400000 + System.currentTimeMillis()) %>";
  var ip = "<%= request.getRemoteAddr() %>";
  // Add to the page using the OpenTok server-side libraries.

  var session;
  var publisher;
  var streams = {};
  var subscribers = {};

  if (TB.checkSystemRequirements() != TB.HAS_REQUIREMENTS) {
    alert('Minimum System Requirements not met!');
  } else {
    session = TB.initSession(sessionId); // Initialize session

    // Add event listeners to the session
    session.addEventListener('sessionConnected', sessionConnectedHandler);
    session.addEventListener('sessionDisconnected', sessionDisconnectedHandler);
    session.addEventListener('streamCreated', streamCreatedHandler);
    session.addEventListener('streamDestroyed', streamDestroyedHandler);
  }

  //--------------------------------------
  //  LINK CLICK HANDLERS
  //--------------------------------------

  function connect() {
    session.connect(apiKey, token);
  }

  function setLocation() {
    $.cookie("locationName", prompt("Enter a name for this location"), {path:"/", expires:9999});
    republish();
  }

  function republish() {
    if (publisher) {
      session.unpublish(publisher);
    }
    $('<div id="opentok_publisher"></div>').prependTo("#myCamera");
    publisher = session.publish('opentok_publisher', {name: ip + ":" + $.cookie("locationName")});
    $("#myLocation").text($.cookie("locationName")).css('display', 'block');
  }

  //--------------------------------------
  //  OPENTOK EVENT HANDLERS
  //--------------------------------------

  function sessionConnectedHandler(event) {
    // Subscribe to all streams currently in the Session
    for ( var i = 0; i < event.streams.length; i++) {
      addStream(event.streams[i]);
    }
    redrawStreams();
    if ($.cookie("locationName")) {
      republish();
    } else {
      setLocation();
    }
  }

  function streamCreatedHandler(event) {
    // Subscribe to these newly created streams
    var streamAdded = false;
    for ( var i = 0; i < event.streams.length; i++) {
      streamAdded |= addStream(event.streams[i]);
    }
    if (streamAdded) {
      redrawStreams();
    }
  }

  function streamDestroyedHandler(event) {
    for (var i = event.streams.length; --i >= 0;) {
      var streamId = event.streams[i].streamId;
      delete streams[streamId];
      delete subscriptions[streamId];
      $("#toggle" + streamId).remove();
    }
  }

  function sessionDisconnectedHandler(event) {
    // This signals that the user was disconnected from the Session. Any subscribers and publishers
    // will automatically be removed. This default behaviour can be prevented using event.preventDefault()
    publisher = null;
    $("#toggles > div").remove();
	connect();
  }

  //--------------------------------------
  //  HELPER METHODS
  //--------------------------------------


  function addStream(stream) {
    if (stream.connection.connectionId == session.connection.connectionId || getStreamIp(stream) == ip) {
      return false;
    }
    var streamName = getStreamName(stream);
    var checked = !$.cookie("uncheckedStreams") || $.cookie("uncheckedStreams").indexOf(":" + streamName + ":") < 0;
    $("#subscribetemplate")
        .tmpl([{streamId: stream.streamId, checked: checked}])
        .appendTo("#toggles");
    $('#check' + stream.streamId).iphoneStyle({checkedLabel: streamName, uncheckedLabel: streamName});
    streams[stream.streamId] = stream;
    return true;
  }

  function showStream(streamId, width, height) {
    $('<div id="' + streamId + '"></div>').prependTo("#subscriptions")
    subscribers[streamId] = session.subscribe(streams[streamId], streamId, {width: width, height: height});
  }

  function hideStream(streamId) {
    if (subscribers[streamId]) {
      session.unsubscribe(subscribers[streamId]);
      delete subscribers[streamId];
    }
  }

  function getStreamIp(stream) {
    return stream.name.slice(0, stream.name.indexOf(":"));
  }

  function getStreamName(stream) {
    return stream.name.slice(stream.name.indexOf(":") + 1);
  }

  function redrawStreams() {
    var normalizedWidth = Math.floor((window.innerWidth - 40) / 4);
    var normalizedHeight = Math.floor((window.innerHeight - 40) / 3);
    var largerDimension = Math.max(normalizedWidth, normalizedHeight);
    var smallerDimension = Math.min(normalizedWidth, normalizedHeight);
    var oblongity = largerDimension / smallerDimension;
    // First find out how many to show.
    var streamsToShow = 1;
    var uncheckedStreams = new Array("");
    for (streamId in streams) {
      if ($("#check" + streamId).is(":checked")) {
        ++streamsToShow;
      } else {
        uncheckedStreams.push(getStreamName(streams[streamId]));
      }
      uncheckedStreams.push("");
      $.cookie("uncheckedStreams", uncheckedStreams.join(":"), {path:"/", expires:9999})
      hideStream(streamId);
    }
    var shortEdgeMax = Math.ceil(Math.sqrt(streamsToShow / oblongity));
    var longEdgeMax = Math.ceil(Math.sqrt(streamsToShow / oblongity) * oblongity);
    var normalizedEdge = Math.max(Math.floor(largerDimension / longEdgeMax), Math.floor(smallerDimension / shortEdgeMax));
    for (streamId in streams) {
      if ($("#check" + streamId).is(":checked")) {
        showStream(streamId, normalizedEdge * 4, normalizedEdge * 3);
      }
    }
  }
</script>
</head>

<body>
<div id="toggles"></div>
<div id="subscriptions">
  <div id="myCamera" style="display:inline-block">
    <button style="display:none" id="myLocation" onclick="javascript:setLocation()"></button>
  </div>
</div>
<script defer="defer">
  connect();
</script>
</body>
</html>
